use crate::components::enums::{
    HttpResponseContentType,AppMode
};
use crate::util;
use ratatui::{Frame, prelude::*, widgets::*};

use crate::components::component::App;

use super::render::choose_color;

// 渲染http ui
pub fn ui(f: &mut Frame, app: &mut App, chunks: &[Rect]) {
    // -- 1. 连接面板 --
    let conn_chunks = Layout::default()
        .direction(Direction::Horizontal)
        .constraints([Constraint::Percentage(50), Constraint::Percentage(50)])
        .split(chunks[0]);

    // **修改 Protocol/Method 显示**
    let method_text = format!("HTTP ({})", app.http_method.to_string().to_uppercase());
    let protocol_block_title =
        crate::ui::render::create_style_title_default(" Protocl / Method", vec!["M"]);
    let protocol_block = Block::default()
        //.title(" Protocol / Method (m) ") // 在标题中提示快捷键
        .title(protocol_block_title)
        .borders(Borders::ALL)
        .border_style(choose_color(false))
        .border_type(BorderType::Rounded);

    let protocol_paragraph = Paragraph::new(method_text).block(protocol_block);
    f.render_widget(protocol_paragraph, conn_chunks[0]);

    // Server Address (S)
    let is_editing_addr = app.mode == AppMode::EditingAddress;
    let addr_text_content = if is_editing_addr {
        &app.current_input
    } else {
        &app.server_addr
    };

    let addr_block_title =
        crate::ui::render::create_style_title_default(" Server Address", vec!["S"]);
    let addr_block = Block::default()
        .title(addr_block_title)
        .borders(Borders::ALL)
        .border_type(BorderType::Rounded)
        .border_style(choose_color(is_editing_addr));
    let addr_paragraph = Paragraph::new(addr_text_content.as_str()).block(addr_block);
    f.render_widget(addr_paragraph, conn_chunks[1]);
    if is_editing_addr {
        util::set_cursor_position(
            f,
            conn_chunks[1].x + 1 + addr_text_content.chars().count() as u16,
            conn_chunks[1].y + 1,
        );
    }

    // -- 2. 发送区域 --
    let send_chunks = Layout::default()
        .direction(Direction::Horizontal)
        .constraints([
            Constraint::Ratio(1, 3),
            Constraint::Ratio(1, 3),
            Constraint::Ratio(1, 3),
        ])
        .split(chunks[1]);

    // Headers (H)
    let header_items: Vec<String> = app
        .request_http_headers
        .iter()
        .map(|(k, v)| format!("{k}: {v}"))
        .collect();
    let title = crate::ui::render::create_style_title_default(" Headers",vec!["H"]);
    crate::ui::render::render_kv_list(
        f,
        app,
        send_chunks[0],
        AppMode::EditingHeaders,
        title,
        "New (key: value)",
        &header_items,
    );

    // Parameters (P)
    let param_items: Vec<String> = app
        .request_http_params
        .iter()
        .map(|(k, v)| format!("{k}={v}"))
        .collect();
    let title = crate::ui::render::create_style_title_default(" Parameters", vec!["P"]);
    crate::ui::render::render_kv_list(
        f,
        app,
        send_chunks[1],
        AppMode::EditingParams,
        title,
        "New (key=value)",
        &param_items,
    );

    // Body (B)
    let is_editing_body = app.mode == AppMode::EditingBody;
    let body_title = format!(" Body [{}] (z) ", app.request_content_type); // 动态标题
    let body_title_styled =
        crate::ui::render::create_style_title_default(&body_title, vec!["B", "z"]);
    let body_text_content = if is_editing_body {
        &app.current_input
    } else {
        &app.request_http_body
    };
    let body_block = Block::default()
        .title(body_title_styled)
        .borders(Borders::ALL)
        .border_type(BorderType::Rounded)
        .border_style(choose_color(is_editing_body));
    let body_paragraph = Paragraph::new(body_text_content.as_str())
        .block(body_block)
        .wrap(Wrap { trim: false });
    f.render_widget(body_paragraph, send_chunks[2]);
    if is_editing_body {
        let (cursor_x, cursor_y) = crate::util::get_cursor_position(
            body_text_content,
            send_chunks[2].width.saturating_sub(2),
        );
        util::set_cursor_position(
            f,
            send_chunks[2].x + 1 + cursor_x,
            send_chunks[2].y + 1 + cursor_y,
        );
    }

    render_http_response_area(f, app, chunks[2]);

    // -- 4. 日志区 --
    let log_block = Block::default()
        .title(" Logs ")
        .borders(Borders::ALL)
        .border_style(choose_color(false))
        .border_type(BorderType::Rounded);
    let log_text = Paragraph::new(app.logs.clone()).block(log_block);
    f.render_widget(log_text, chunks[3]);
}

/// =========================================================================
/// ==          渲染整个 HTTP 响应区域的函数                         ==
/// =========================================================================
fn render_http_response_area(f: &mut Frame, app: &mut App, area: Rect) {
    let outer_block = Block::default()
        .title(" HTTP Response-body ('c' to copy)")
        .borders(Borders::ALL)
        .border_style(choose_color(false))
        .border_type(BorderType::Rounded);
    f.render_widget(outer_block, area);

    // 如果还没有响应(即还没有发起请求)，显示提示信息
    if app.not_request_yet() {
        let placeholder = Paragraph::new("Press <Space> to send the request.")
            .style(Style::default().fg(Color::DarkGray))
            .alignment(Alignment::Center);
        f.render_widget(placeholder, area);
        // 此时终止逻辑，返回
        return;
    }

    // 如果发起了请求并且有了相应，将区域水平切分为左右两栏
    let response_chunks = Layout::default()
        .direction(Direction::Horizontal)
        .margin(1) // 在外边框内部留出边距
        .constraints([
            Constraint::Percentage(60), // 左侧给 Body
            Constraint::Percentage(40), // 右侧给元数据
        ])
        .split(area);

    // body部分
    render_response_body(f, app, response_chunks[0]);
    // 元数据部分
    render_response_metadata(f, app, response_chunks[1]);
}

// =========================================================================
// ==          渲染左侧的响应 Body                                  ==
// =========================================================================
fn render_response_body(f: &mut Frame, app: &mut App, area: Rect) {
    let content_type_str = format!("{:?}", app.response_content_type);
    let title = format!(" Response Body ({content_type_str}) ");

    let formatted_body = format_body(&app.response_http_body, app.response_content_type);

    // 在渲染前，计算并校准滚动位置
    let max_scroll = util::calculate_max_scroll(&formatted_body, area);
    app.scroll_position = app.scroll_position.min(max_scroll);

    let body_paragraph = Paragraph::new(formatted_body)
        .block(Block::default().title(title).borders(Borders::TOP))
        .wrap(Wrap { trim: false })
        .scroll((app.scroll_position as u16, 0)); // 应用滚动

    f.render_widget(body_paragraph, area);
}
// =========================================================================
// ==          渲染右侧的元数据 (Status, Headers, Cookies)          ==
// =========================================================================
fn render_response_metadata(f: &mut Frame, app: &mut App, area: Rect) {
    // 将右侧区域垂直切分为三块
    let metadata_chunks = Layout::default()
        .direction(Direction::Vertical)
        .constraints([
            Constraint::Length(3), // Status
            Constraint::Length(7), // Cookies
            Constraint::Min(0),    // Headers
        ])
        .split(area);

    // --- Status --- 不同的http.status渲染不同颜色
    let status_color = match app.response_http_status_code {
        200..=299 => Color::Green,
        400..=499 => Color::Yellow,
        500..=599 => Color::Red,
        _ => Color::Gray,
    };
    let span = Span::raw(app.response_http_status_code.to_string())
        .style(Style::default().fg(Color::White));
    let status_text = Paragraph::new(span)
        .style(Style::default().bg(status_color))
        .block(Block::default().title(" Status ").borders(Borders::ALL));
    f.render_widget(status_text, metadata_chunks[0]);

    // --- Cookies ---
    let cookies = extract_cookies(&app.response_http_headers);
    app.response_http_cookies = cookies.clone();
    let cookie_items: Vec<ListItem> = cookies.iter().map(|c| ListItem::new(c.as_str())).collect();
    let cookie_list =
        List::new(cookie_items).block(Block::default().title(" Cookies ('j' to copy)").borders(Borders::ALL));
    f.render_widget(cookie_list, metadata_chunks[1]);

    // --- Headers ---
    let header_items: Vec<ListItem> = app
        .response_http_headers
        .iter()
        .map(|(k, v)| ListItem::new(format!("{k}: {v}")))
        .collect();
    let header_list =
        List::new(header_items).block(Block::default().title(" Headers ('n' to copy)").borders(Borders::ALL));
    f.render_widget(header_list, metadata_chunks[2]);
}

// =========================================================================
// ==          格式化 Body 和提取 Cookies 的辅助函数                  ==
// =========================================================================

// 根据 Content-Type 格式化 Body
fn format_body(body: &str, content_type: HttpResponseContentType) -> String {
    if content_type == HttpResponseContentType::Json {
        // 尝试美化 JSON
        if let Ok(json_value) = serde_json::from_str::<serde_json::Value>(body) {
            if let Ok(pretty_json) = serde_json::to_string_pretty(&json_value) {
                return pretty_json;
            }
        }
    }
    // 对于 XML, HTML, Text 或格式化失败的 JSON，直接返回原字符串
    body.to_string()
}

// 从 Headers 中提取 Cookies
fn extract_cookies(headers: &[(String, String)]) -> Vec<String> {
    headers
        .iter()
        .filter(|(k, _)| k.eq_ignore_ascii_case("Set-Cookie"))
        .map(|(_, v)| v.split(';').next().unwrap_or("").to_string()) // 只取 key=value 部分
        .collect()
}
